#pragma
#include"InetAddr.hpp"
#include<iostream>
#include"nocopy.hpp"
#include<sys/types.h>
#include<sys/socket.h>
#include<unistd.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include"Log.hpp"
#include<cstring>
using namespace std;
static const int gsockfd = -1;
static const int glocalport = 6666;
enum
{
    SOCKET_ERROR = 1,
    BIND_ERROR
};
class UdpServer : public nocopy
{
public:
    // UdpServer(const string &localip,const int localport=glocalport):_sockfd(gsockfd),_localport(localport),_locapip(localip)
    // {}
    UdpServer(const int localport=glocalport):_sockfd(gsockfd),_localport(localport)
    {}
    void InitServer()
    {
        _sockfd = ::socket(AF_INET, SOCK_DGRAM, 0);
        if(_sockfd<0)
        {
            LOG(FATAL, "socket error\n");
            exit(SOCKET_ERROR);
        }
        LOG(DEBUG, "socket create success,fd:%d\n", _sockfd);
        //绑定端口号
        struct sockaddr_in local;
        memset(&local, 0, sizeof(local));
        local.sin_family = AF_INET;
        local.sin_port = htons(_localport);
        //local.sin_addr.s_addr = inet_addr(_localip.c_str());//转4字节IP，需要网络序列的IP
        local.sin_addr.s_addr=INADDR_ANY;//不能绑定固定IP，否则只能收到这个IP发的信息
        
        int n = ::bind(_sockfd, (struct sockaddr*)&local, sizeof(local));
        if(n<0)
        {
            LOG(FATAL,"bind error\n");
            exit(BIND_ERROR);
        }
        LOG(DEBUG, "bind success\n");
    }
    void Start()
    {
        _isrunning = true;
        char buf[512];
        while (1)
        {
            struct sockaddr_in peer;
            socklen_t len = sizeof(peer);
            ssize_t n = recvfrom(_sockfd, buf, sizeof(buf) - 1, 0, (struct sockaddr *)&peer, &len);
            if(n>0)
            {
                buf[n] = 0;
                InetAddr ad(peer);
                cout << '[' << ad.Ip() << ':' << ad.Port() << "]:" << buf << endl;
                string msg = "[udpserver-echo]:";
                msg += buf;
                sendto(_sockfd, msg.c_str(), msg.size(), 0, (struct sockaddr *)&peer, len);
            }
            else
            {
                LOG(ERROR, "receive error\n");
            }
        }
    }
    ~UdpServer()
    {
        if(_sockfd>gsockfd)
            ::close(_sockfd);
    }

private:
    int _sockfd;
    int _localport;
    //string _localip;
    bool _isrunning = false;
};